﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using RainEngine.SceneManagement;
using RainEngine.SceneNodes;

namespace Sample03
{
    /// <summary>
    /// 坦克模型，从ModelSceneNode继承，添加了层次模型的支持
    /// </summary>
    public class tankModel : ModelSceneNode
    {
        #region 成员变量、属性和构造函数
                
        //需要跟随的地形
        SimpleTerrainSceneNode terrain;

        //坦克各部件的Bone。
        ModelBone turretBone;
        ModelBone cannonBone;
        ModelBone lSteerEngineBone;
        ModelBone rSteerEngineBone;
        ModelBone leftBackWheelBone;
        ModelBone rightBackWheelBone;
        ModelBone leftFrontWheelBone;
        ModelBone rightFrontWheelBone;
       
        //坦克各部件Bone的转换矩阵
        Matrix turretTransform;
        Matrix cannonTransform;
        Matrix lSteerEngineTransform;
        Matrix rSteerEngineTransform;
        Matrix leftBackWheelTransform;
        Matrix rightBackWheelTransform;
        Matrix leftFrontWheelTransform;
        Matrix rightFrontWheelTransform;
        
        //车轮自转的旋转矩阵
        Matrix wheelRollMatrix;

        //各部件的旋转量
        float turretRotationValue;
        float cannonRotationValue;
        float steerRotationValue;
        float wheelRotationValue;

        /// <summary>
        /// 炮管、炮塔旋转的最大角速度
        /// </summary>
        public const float MaxCannonSpeed = 1f;

        /// <summary>
        /// 炮塔的旋转范围
        /// </summary>
        private const float MaxTurretAngle = 1.0f;
        private const float MinTurretAngle = -1.0f;

        /// <summary>
        /// 炮管的旋转范围
        /// </summary>
        private const float MaxCannonAngle = 0.0f;
        private const float MinCannonAngle = -0.9f;

        /// <summary>
        /// 获取或设置车轮的旋转量
        /// </summary>
        public float WheelRotationValue
        {
            get { return wheelRotationValue; }
            set { wheelRotationValue = value; }
        }

        /// <summary>
        /// 获取或设置前轮轴的旋转量
        /// </summary>
        public float SteerRotationValue
        {
            get { return steerRotationValue; }
            set { steerRotationValue = value; }
        }

        /// <summary>
        /// 获取或设置炮塔旋转量
        /// </summary>
        public float TurretRotation
        {
            get { return turretRotationValue; }
            set
            {
                if (value > MaxTurretAngle)
                    turretRotationValue = MaxTurretAngle;
                else if (value < MinTurretAngle)
                    turretRotationValue = MinTurretAngle;
                else
                    turretRotationValue = value;
            }
        }

        /// <summary>
        /// 获取或设置炮管旋转量
        /// </summary>
        public float CannonRotation
        {
            get { return cannonRotationValue; }
            set
            {
                if (value > MaxCannonAngle)
                    cannonRotationValue = MaxCannonAngle;
                else if (value < MinCannonAngle)
                    cannonRotationValue = MinCannonAngle;
                else
                    cannonRotationValue = value;
            }
        }
                
        /// <summary>
        /// 创建一个ModelSceneNode对象。
        /// </summary>
        /// <param name="engine">引擎</param>
        /// <param name="modelAssetName">模型名称</param>
        public tankModel(GraphicsDevice setGraphicsDevice, ContentManager setContent,Scene setScene, string modelAssetName, SimpleTerrainSceneNode terrain)
            : base(setGraphicsDevice, setContent,setScene , modelAssetName)
        {
            this.terrain = terrain;
        }

        #endregion               

        /// <summary>
        /// 初始化节点。
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();
            
            // 获取坦克各部件的Bone。
            turretBone = model.Bones["turret_geo"];
            cannonBone = model.Bones["canon_geo"];
            lSteerEngineBone = model.Bones["l_steer_geo"];
            rSteerEngineBone = model.Bones["r_steer_geo"];            
            leftBackWheelBone = model.Bones["l_back_wheel_geo"];
            rightBackWheelBone = model.Bones["r_back_wheel_geo"];
            leftFrontWheelBone = model.Bones["l_front_wheel_geo"];
            rightFrontWheelBone = model.Bones["r_front_wheel_geo"];
            
            //获取坦克各部件的转换矩阵
            turretTransform = turretBone.Transform;
            cannonTransform = cannonBone.Transform;
            lSteerEngineTransform =lSteerEngineBone .Transform ;
            rSteerEngineTransform = rSteerEngineBone.Transform;            
            leftBackWheelTransform = leftBackWheelBone.Transform;
            rightBackWheelTransform = rightBackWheelBone.Transform;
            leftFrontWheelTransform = leftFrontWheelBone.Transform;
            rightFrontWheelTransform = rightFrontWheelBone.Transform;
        }

        public override void Update(GameTime gameTime)
        {
            
            base.Update(gameTime);

            //根据旋转量重新计算变换矩阵
            turretBone.Transform = Matrix.CreateRotationY(turretRotationValue) * turretTransform;
            cannonBone.Transform = Matrix.CreateRotationX(cannonRotationValue) * cannonTransform;
            lSteerEngineBone.Transform=Matrix.CreateRotationY(steerRotationValue) * lSteerEngineTransform ;
            rSteerEngineBone.Transform = Matrix.CreateRotationY(steerRotationValue) * rSteerEngineTransform;
            
            wheelRollMatrix *= Matrix.CreateRotationX(wheelRotationValue );
            leftBackWheelBone.Transform = Matrix.CreateRotationX(wheelRotationValue ) * leftBackWheelTransform;
            rightBackWheelBone.Transform = Matrix.CreateRotationX(wheelRotationValue) * rightBackWheelTransform;
            leftFrontWheelBone.Transform = Matrix.CreateRotationX(wheelRotationValue) * leftFrontWheelTransform;
            rightFrontWheelBone.Transform = Matrix.CreateRotationX(wheelRotationValue) * rightFrontWheelTransform;            
        }
        
        /// <summary>
        /// 绘制坦克。
        /// </summary>
        /// <param name="gameTime"></param>        
        public override int Draw(GameTime gameTime, Matrix ViewMatrix, Matrix ProjectionMatrix, Vector3 CameraPosition)
        {
            model.CopyAbsoluteBoneTransformsTo(modelTransforms);
            
            return base.Draw(gameTime,ViewMatrix, ProjectionMatrix, CameraPosition);  
        } 
    }
}
